﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;

namespace TechnicalAnalysisEngine.Tests
{
    [TestClass]
    public class TestStandardDeviation
    {
        List<double> inputValues;
        List<double> expectedValues;

        int periods;

        [TestInitialize]
        public void Initialize()
        {
            inputValues = new List<double>()
            {
                86.16,89.09,88.78,90.32,89.07,91.15,89.44,89.18,86.93,87.68,86.96,89.43,89.32,88.72,87.45,87.26,89.50,87.90,89.13,90.70,92.90,92.98,
                91.80,92.66,92.68,92.30,92.77,92.54,92.95,93.20,91.07,89.83,89.74,90.40,90.74,88.02,88.09,88.84,90.78,90.54,91.39,90.65

            };

            expectedValues = new List<double>()
            {
                1.29,1.45,1.69,1.77,1.90,2.02,2.08,2.18,2.24,2.20,2.19,2.02,2.01,2.00,1.94,1.76,1.68,1.78,1.70,1.64,1.65,1.60,1.55
            };

            periods = 20;
        }

        [TestMethod]
        public void TestStdev()
        {
            List<double> resultList = new List<double>();

            for (int i = 0; i < inputValues.Count - periods + 1; i++)
            {
                resultList.Add(Helpers.StandardDeviation(inputValues.Skip(i).Take(periods)));
            }

            Assert.AreEqual(resultList.Count, expectedValues.Count, string.Format("Expected: {0}, Actual: {1} ", expectedValues.Count, resultList.Count));

            bool result = true;
            string message = null;

            for (int i = 0; i < resultList.Count; i++)
            {
                if (!TestHelpers.EqualsWithTolerance(resultList[i], expectedValues[i], 1))
                {
                    message = string.Format("Values do not match at position {0}, expected: {1}, actual: {2} ",
                        i, expectedValues[i], resultList[i]);

                    result = false;
                    break;
                }
            }

            Assert.IsTrue(result, message);
        }

        [TestMethod]
        public void TestStdevPerformance()
        {
            List<double> resultList = new List<double>();

            Random random = new Random();
            var randomlyGeneratedValues = new List<double>();

            for (int i = 0; i < 10000; i++)
            {
                randomlyGeneratedValues.Add(random.Next(85, 90));
            }

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            for (int i = 0; i < randomlyGeneratedValues.Count - periods + 1; i++)
            {
                resultList.Add(Helpers.StandardDeviation(randomlyGeneratedValues.GetRange(i, periods)));
            }

            stopWatch.Stop();
            Console.WriteLine(string.Format("Stdev, {0} values, {1} μs", randomlyGeneratedValues.Count, stopWatch.ElapsedTicks / 10));
        }
    }
}
